<template>
  <div class="el-tree-select" ref="wrap">
    <el-popover
      placement="bottom-start"
      width="320"
      v-model="visible"
      trigger="manual"
      popper-class="tree-select-popper"
    >
      <!-- 输入框 -->
      <template #reference>
        <el-input
          :placeholder="placeholder"
          :value="displayLabel"
          readonly
          style="width: 100%"
          @click.native.stop="handleInputClick"
          :clearable="clearable"
          @clear.stop.prevent="clearSelection"
          :disabled="isDisabled"
        >
          <template #suffix>
            <i class="el-icon-arrow-down" :class="{ open: visible, disabled: isDisabled }"></i>
          </template>
        </el-input>
      </template>

      <!-- 树形内容 -->
      <div class="tree-wrap">
        <el-tree
          ref="tree"
          :data="formattedData"
          :props="treeProps"
          :expand-on-click-node="false"
          :highlight-current="true"
          :show-checkbox="multiple"
          node-key="__tree_select_key"
          @node-click="handleNodeClick"
          @check-change="handleCheckChange"
        >
          <template #default="{ node, data }">
            <span :class="['custom-tree-node', { 'is-disabled': isNodeDisabled(data) }]">
              <span>{{ node.label }}</span>
              <i v-if="isNodeDisabled(data)" class="el-icon-warning-outline disabled-icon"></i>
            </span>
          </template>
        </el-tree>
      </div>
    </el-popover>
  </div>
</template>

<script>
export default {
  name: "TreeSelect",
  props: {
    value: null,
    data: { type: Array, required: true },
    valueFields: {
      type: Object,
      default: () => ({ parent: "id", child: "id" }),
    },
    labelField: {
      type: [String, Object, Function],
      default: "label",
    },
    nodeKeyFields: {
      type: Object,
      default: () => ({ parent: "id", child: "id" }),
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
    clearable: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      visible: false,
      internalValue: this.value,
    };
  },
  computed: {
    isDisabled() {
      if (this.multiple) {
        if (!Array.isArray(this.internalValue) || this.internalValue.length === 0) {
          return false;
        }
        return this.internalValue.some(val => {
          const node = this.findNodeByValue(val);
          return node && this.isNodeDisabled(node);
        });
      } else {
        if (!this.internalValue) return false;
        const node = this.findNodeByValue(this.internalValue);
        return node && this.isNodeDisabled(node);
      }
    },
    treeProps() {
      return {
        children: 'children',
        label: '__tree_label',
        disabled: this.isNodeDisabled
      };
    },
    formattedData() {
      const format = (list) => {
        return list.map((item) => {
          const isParent = "children" in item;

          let label = "";
          if (typeof this.labelField === "function") {
            label = this.labelField(item);
          } else if (typeof this.labelField === "object") {
            const field = isParent
              ? this.labelField.parent
              : this.labelField.child;
            label = item[field] !== undefined ? item[field] : "";
          } else {
            label = item[this.labelField] || "";
          }

          const keyField = isParent
            ? this.nodeKeyFields.parent
            : this.nodeKeyFields.child;
          const keyVal =
            item[keyField] || item.id || Math.random().toString(36).slice(2);

          const node = {
            ...item,
            __tree_label: label,
            __tree_select_key: keyVal,
            __is_parent: isParent
          };

          if (item.children && item.children.length > 0) {
            node.children = format(item.children);
          }

          return node;
        });
      };
      return format(this.data);
    },
    displayLabel() {
      if (this.multiple) {
        if (!Array.isArray(this.internalValue) || this.internalValue.length === 0)
          return "";
        const labels = this.internalValue.map((v) => {
          const node = this.findNodeByValue(v);
          return node ? node.__tree_label : v;
        });
        return labels.join(", ");
      } else {
        if (!this.internalValue) return "";
        const node = this.findNodeByValue(this.internalValue);
        return node ? node.__tree_label : String(this.internalValue);
      }
    },
  },
  watch: {
    value(val) {
      this.internalValue = val;
    },
  },
  mounted() {
    document.addEventListener("click", this.handleOutsideClick);
  },
  beforeDestroy() {
    document.removeEventListener("click", this.handleOutsideClick);
  },
  methods: {
    isNodeDisabled(data) {
      // 父节点或enableState为1的节点都禁用
      return data.__is_parent || data.enableState === '1';
    },
    handleInputClick() {
      if (!this.isDisabled) {
        this.toggleVisible();
      }
    },
    toggleVisible() {
      this.visible = !this.visible;
    },
    clearSelection() {
      if (this.isDisabled) return;
      this.internalValue = this.multiple ? [] : null;
      this.$emit("input", this.internalValue);
      if (this.multiple && this.$refs.tree) this.$refs.tree.setCheckedKeys([]);
    },
    handleOutsideClick(e) {
      if (this.$refs.wrap && !this.$refs.wrap.contains(e.target)) {
        this.visible = false;
      }
    },
    handleNodeClick(data, node) {
      if (this.multiple || this.isNodeDisabled(data)) return;
      const val = this.computeValue(data);
      if (val === undefined) return; // 父节点没有有效值
      this.internalValue = val;
      this.$emit("input", val);
      this.$emit("change", val);
      this.visible = false;
    },
    handleCheckChange() {
      if (!this.multiple) return;
      // 只获取叶子节点的选中状态
      const checkedNodes = this.$refs.tree.getCheckedNodes(true).filter(n => !n.__is_parent);
      const values = checkedNodes.map((n) => this.computeValue(n));
      this.internalValue = values;
      this.$emit("input", values);
      this.$emit("change", values);
    },
    computeValue(data) {
      // 如果是父节点，返回undefined
      if (data.__is_parent) return undefined;
      return data[this.valueFields.child];
    },
    findNodeByValue(val) {
      const dfs = (list) => {
        for (const item of list) {
          const isParent = "children" in item;
          const f = isParent ? this.valueFields.parent : this.valueFields.child;
          if (item[f] === val) return item;
          if (item.children) {
            const res = dfs(item.children);
            if (res) return res;
          }
        }
        return null;
      };
      return dfs(this.formattedData);
    },
  },
};
</script>

<style scoped>
.el-tree-select {
  position: relative;
  display: inline-block;
  width: 320px;
}
.el-tree-select .el-input {
  cursor: pointer;
}
.el-icon-arrow-down {
  transition: transform 0.2s;
}
.el-icon-arrow-down.open {
  transform: rotate(180deg);
}
.el-icon-arrow-down.disabled {
  color: #c0c4cc;
  cursor: not-allowed;
}
.tree-wrap {
  max-height: 300px;
  overflow: auto;
}
.tree-select-popper {
  z-index: 3000 !important;
}

/* 自定义节点样式 */
.custom-tree-node {
  display: flex;
  align-items: center;
  width: 100%;
}
.custom-tree-node.is-disabled {
  color: #c0c4cc;
  cursor: not-allowed;
}
.custom-tree-node.is-disabled:hover {
  background-color: #f5f7fa;
}
.disabled-icon {
  margin-left: 5px;
  color: #f56c6c;
}
</style>
